import json
import time
import logging
import uuid
import cloudscraper
from typing import Dict, Any, AsyncGenerator

from fastapi import HTTPException
from fastapi.responses import StreamingResponse, JSONResponse

from app.core.config import settings
from app.providers.base_provider import BaseProvider
from app.utils.sse_utils import create_sse_data, create_chat_completion_chunk, DONE_CHUNK

logger = logging.getLogger(__name__)

class FlowithProvider(BaseProvider):
    def __init__(self):
        # 使用同一个 scraper 实例来保持会话和 Cookie
        self.scraper = cloudscraper.create_scraper()
        self.chat_api_url = "https://edge.flowith.net/ai/chat?mode=general"

    def _prepare_supabase_headers(self) -> Dict[str, str]:
        """准备访问 Supabase 的请求头"""
        return {
            'accept': 'application/json',
            'apikey': settings.SUPABASE_ANON_KEY,
            'authorization': f'Bearer {settings.SUPABASE_ANON_KEY}',
            'accept-profile': 'public',
            'x-client-info': 'supabase-js-web/2.51.0',
            'origin': 'https://flowith.net',
            'referer': 'https://flowith.net/',
        }

    def _pre_authorize_session(self) -> str:
        """
        通过与 Supabase 交互来预授权会话，并获取一个有效的 conversation_id。
        这是解决 429/401 错误的关键步骤。
        """
        conv_id = str(uuid.uuid4())
        url = f"{settings.SUPABASE_URL}/rest/v1/cooperate?select=*&conv_id=eq.{conv_id}&user_id=eq.{uuid.uuid4()}"
        headers = self._prepare_supabase_headers()
        headers['accept'] = 'application/vnd.pgrst.object+json' # 特殊的 accept 头

        try:
            logger.info(f"正在预授权会话，目标 URL: {url}")
            # 使用共享的 scraper 实例发送请求
            response = self.scraper.get(url, headers=headers, timeout=20)
            # 即使预授权失败（例如返回406），这个交互过程本身可能已经为会话设置了必要的 Cookie 或状态
            # 所以我们不在这里 raise_for_status()，而是记录并继续
            if response.status_code >= 400:
                 logger.warning(f"预授权请求返回状态码 {response.status_code}，但仍将继续尝试。响应: {response.text}")
            else:
                logger.info(f"预授权步骤成功，状态码: {response.status_code}。")
            
            # 返回生成的 conversation_id 用于可能的后续步骤
            return conv_id
        except Exception as e:
            logger.error(f"预授权步骤发生严重错误: {e}", exc_info=True)
            raise HTTPException(status_code=503, detail=f"无法完成会话预授权: {e}")

    async def chat_completion(self, request_data: Dict[str, Any]) -> StreamingResponse:
        
        # 在异步生成器外部执行同步的预授权
        try:
            self._pre_authorize_session()
        except HTTPException as e:
            # 如果预授权直接失败，立即返回错误
            async def error_stream():
                yield create_sse_data({"error": {"message": e.detail, "code": e.status_code}})
                yield DONE_CHUNK
            return StreamingResponse(error_stream(), media_type="text/event-stream")

        async def stream_generator() -> AsyncGenerator[bytes, None]:
            request_id = f"chatcmpl-{uuid.uuid4()}"
            model_name = request_data.get("model", settings.DEFAULT_MODEL)
            
            try:
                payload = self._prepare_payload(request_data)
                headers = self._prepare_chat_headers()

                logger.info(f"发起聊天请求到 {self.chat_api_url}")
                response = self.scraper.post(
                    self.chat_api_url, 
                    headers=headers, 
                    json=payload, 
                    stream=True, 
                    timeout=settings.API_REQUEST_TIMEOUT
                )
                response.raise_for_status()

                for line in response.iter_lines():
                    if not line:
                        continue
                    try:
                        chunk_content = line.decode('utf-8')
                        chunk = create_chat_completion_chunk(request_id, model_name, chunk_content)
                        yield create_sse_data(chunk)
                    except Exception as line_error:
                        logger.warning(f"无法处理流中的行: {line}. 错误: {line_error}")
                        continue
                
                final_chunk = create_chat_completion_chunk(request_id, model_name, "", "stop")
                yield create_sse_data(final_chunk)
                yield DONE_CHUNK

            except Exception as e:
                logger.error(f"处理流时发生错误: {e}", exc_info=True)
                error_message = f"内部服务器错误: {str(e)}"
                error_chunk = create_chat_completion_chunk(request_id, model_name, error_message, "stop")
                yield create_sse_data(error_chunk)
                yield DONE_CHUNK

        return StreamingResponse(stream_generator(), media_type="text/event-stream")

    def _prepare_chat_headers(self) -> Dict[str, str]:
        return {
            "Accept": "*/*",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
            "Authorization": "",
            "Content-Type": "application/json",
            "Origin": "https://flowith.net",
            "Referer": "https://flowith.net/",
            "responsetype": "stream",
        }

    def _prepare_payload(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
        messages = request_data.get("messages", [])
        api_model_name = request_data.get("model", settings.DEFAULT_MODEL)
        upstream_model = api_model_name.replace("flowith-", "")
        
        return {
            "stream": True,
            "model": upstream_model,
            "messages": messages,
            "nodeId": str(uuid.uuid4()),
        }

    async def get_models(self) -> JSONResponse:
        model_data = {
            "object": "list",
            "data": [
                {"id": name, "object": "model", "created": int(time.time()), "owned_by": "lzA6"}
                for name in settings.KNOWN_MODELS
            ]
        }
        return JSONResponse(content=model_data)
